home *** CD-ROM | disk | FTP | other *** search
/ Aminet 34 / Aminet 34 (2000)(Schatztruhe)[!][Dec 1999].iso / Aminet / util / gnu / unixcmds.lha / unixcmds / src / unshar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-06  |  10.8 KB  |  374 lines

  1. /* unshar - extract files from a shell archive  Author: Warren Toomey */
  2.  
  3. /* Copyright 1989 by Warren Toomey      wkt@cs.adfa.oz.au[@uunet.uu.net]
  4.  *
  5.  * You may freely copy or distribute this code as long as this notice
  6.  * remains intact.
  7.  *
  8.  * You may modify this code, as long as this notice remains intact, and
  9.  * you add another notice indicating that the code has been modified.
  10.  *
  11.  * You may NOT sell this code or in any way profit from this code without
  12.  * prior agreement from the author.
  13.  *
  14.  * Modified by Andy Tanenbaum, Nov. 1992
  15.  * Modified by Bruce Evans, Jan. 1993
  16.  */
  17.  
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <stdio.h>
  21. #include "getopt.h"
  22.  
  23. /* Methods of unsharing */
  24. #define UNKNOWN 0
  25. #define BRUTAL  1
  26.  
  27. /* Whitespace indicators */
  28. #define WHITE   0
  29. #define NOWHITE 1
  30.  
  31. /* Leading character indicators */
  32. #define NOX     0
  33. #define YESX    1
  34.  
  35. /* Misc. constants */
  36. #define BUFSIZE 512             /* Size of line buffer */
  37.  
  38. /* Emulation types available */
  39. #define NUMTOKS    4            /* NUMTOKS must equal # of emulation types */
  40. #define SED        1
  41. #define GRES       2
  42. #define CAT        3
  43.  
  44. /* The list of emulation types. */
  45. static char *token[NUMTOKS] = {"", "sed", "gres", "cat"};
  46.  
  47. /* Global variables */
  48. int table;                      /* Generate a table, or extract */
  49. int numext;                     /* Number of files to extract */
  50. unsigned long nulchars;         /* # Nuls discarded from input */
  51. unsigned long overrunchars;     /* # Chars overruning line buffers */
  52. char *exfile[100];              /* Files to extract */
  53.  
  54. extern char *optarg;
  55.  
  56. int main  (int argc, char **argv);
  57. int fgetline  (FILE * zin, int how, char *buf, size_t max);
  58. char *getstring  (char *buf);
  59. int firstword  (char *buf);
  60. int mustget  (char *s1);
  61. void extract  (int how, char *file, char *end, char *lead);
  62. void getnames  (char *buf, char *file, char *word);
  63. void disembowel  (void);
  64. void usage  (void);
  65.  
  66. int main(argc, argv)
  67. /* [<][>][^][v][top][bottom][index][help] */
  68. int argc;
  69. char *argv[];
  70. {
  71.   int i, c, first;
  72.   int method;                   /* Method of unsharing */
  73.  
  74.   method = BRUTAL;              /* Only BRUTAL currently available */
  75.   table = 0;                    /* Don't generate a table */
  76.   numext = 0;                   /* Initially no files to extract */
  77.  
  78.   while ((c = getopt(argc, argv, "x:tbv")) != EOF) switch (c) {
  79.             case 't':
  80.                 table = 1;      /* Get the various options */
  81.                 break;
  82.  
  83.             case 'b':   method = BRUTAL;        break;
  84.             case 'x':
  85.                 exfile[numext] = (char *) malloc(strlen(optarg) + 1);
  86.                 strcpy(exfile[numext++], optarg);
  87.                 break;
  88.  
  89.             default:    usage();
  90.         }
  91.  
  92.   if (argc == 1) {
  93.         first = argc;           /* Find first file argument */
  94.   } else {
  95.         for (first = 1; first < argc; first++)
  96.                 if (argv[first][0] != '-') break;
  97.   }
  98.  
  99.   if (first == argc) {          /* If no file argument use stdin only */
  100.         switch (method) {
  101.             case BRUTAL:
  102.                 disembowel();   /* Unshar brutally! */
  103.                 break;
  104.  
  105.             default:
  106.                 fprintf(stderr, "unshar: Unknown method of unsharing\n");
  107.                 exit(1);
  108.         }
  109.   } else {
  110.         for (i = first; i < argc; i++) {        /* open stdio with every
  111.                                                  * file */
  112.                 if (table) printf("%s:\n", argv[i]);
  113.                 if (freopen(argv[i], "r", stdin) != stdin) {
  114.                         perror("unshar");
  115.                         exit(1);
  116.                 }
  117.                 switch (method) {
  118.                     case BRUTAL:
  119.                         disembowel();   /* Unshar brutally! */
  120.                         break;
  121.  
  122.                     default:
  123.                         fprintf(stderr,"unshar: Unknown method of unsharing\n");
  124.                         exit(1);
  125.                 }
  126.         }
  127.   }
  128.   return(0);
  129. }
  130.  
  131. int fgetline(zin, how, buf, max)
  132. /* [<][>][^][v][top][bottom][index][help] */
  133. FILE *zin;
  134. int how;                        /* Ignore leading whitespace if how=NOWHITE */
  135. char *buf;
  136. size_t max;                     /* Buffer size, must be >= 2 */
  137. {
  138. /* Get a line from a file */
  139.   int ch = 0;
  140.   char *limit = buf + max - 1;
  141.  
  142.   *buf = 0;                     /* Null the buffer */
  143.   if (how == NOWHITE) {         /* If skip any whitespace */
  144.         while (((ch = getc(zin)) == ' ') || (ch == '\t'));
  145.         if (ch == EOF) return(EOF);     /* Returning EOF or 0 */
  146.         if (ch == '\n') return (0);
  147.         *buf++ = ch;            /* Put char in buffer */
  148.   }
  149.   while ((ch = getc(zin)) != '\n') {    /* Now get the line */
  150.         if (ch == EOF) {
  151.                 *buf = 0;
  152.                 return(EOF);
  153.         }
  154.         if (ch == 0) {
  155.                 nulchars++;
  156.                 continue;
  157.         }
  158.         if (buf == limit)
  159.                 overrunchars++;
  160.         else
  161.                 *buf++ = ch;
  162.   }
  163.  
  164.   *buf = 0;                     /* Finally null-terminate the buffer */
  165.   return(0);                    /* and return */
  166. }
  167.  
  168. char *getstring(buf)
  169. /* [<][>][^][v][top][bottom][index][help] */
  170. char *buf;
  171. {
  172. /* Get the next string from the buffer ignoring any quotes. */
  173.   char out[BUFSIZE];
  174.   char *temp = out;
  175.   char inquotes = 0, ok = 1;
  176.   while ((*buf == ' ') || (*buf == '\t'))
  177.         buf++;                  /* Skip whitespace */
  178.  
  179.   *temp = 0;
  180.   while (ok) {                  /* Parse line */
  181.         switch (*buf) {
  182.             case '\"':
  183.             case '\'':
  184.                 buf++;
  185.                 inquotes = !inquotes;   /* Toggle inquotes */
  186.                 break;
  187.  
  188.             case 0:
  189.             case '\n':          /* Stop on <, >, NULL */
  190.             case '>':           /* \n, and sometimes */
  191.             case '<':   ok = 0; break;  /* space & tab */
  192.             case '\t':
  193.             case ' ':
  194.                 if (!inquotes) ok = 0;
  195.             case '\\':
  196.                 if (!inquotes) {/* Ignore backquotes */
  197.                         buf++;
  198.                         break;
  199.                 }
  200.  
  201.             default:
  202.                 *temp++ = *buf++;       /* Copy chars :-) */
  203.         }
  204.   }
  205.   *temp = 0;
  206.   return(out);
  207. }
  208.  
  209. int firstword(buf)
  210. /* [<][>][^][v][top][bottom][index][help] */
  211. char *buf;
  212. {
  213. /* Return token value of the first word in the buffer.  Assume no leading
  214.  * white space in the buffer.
  215.  */
  216.   int i;
  217.  
  218.   for (i = 1; i < NUMTOKS; i++)
  219.         if (strncmp(buf, token[i], strlen(token[i])) == 0) return(i);
  220.  
  221.   return(UNKNOWN);
  222. }
  223.  
  224. int mustget(s1)
  225. /* [<][>][^][v][top][bottom][index][help] */
  226. char *s1;
  227. {
  228. /* Return 1 if s1 is in he list of files to extract.  Else return 0. */
  229.   int i;
  230.  
  231.   if (numext == 0) return(0);
  232.   for (i = 0; i < numext; i++)
  233.         if (!strcmp(s1, exfile[i])) return(1);
  234.   return(0);
  235. }
  236.  
  237. void extract(how, file, end, lead)
  238. /* [<][>][^][v][top][bottom][index][help] */
  239. int how;                /* If how==YESX, ignore 1st char on each line */
  240. char *file;
  241. char *end;
  242. char *lead;
  243. {
  244. /* Extract file, up until end word */
  245.   FILE *zout;
  246.   char line[BUFSIZE];
  247.   char *temp;
  248.   int ch, match;
  249.   size_t n;
  250.  
  251.   n = strlen(lead);
  252.   zout = fopen(file, "w");      /* Open output file */
  253.   if (zout == NULL) {
  254.         perror("unshar");
  255.         return;
  256.   }
  257.   while (1) {
  258.         ch = fgetline(stdin, WHITE, line, sizeof line);
  259.         temp = line;
  260.         if (ch == EOF) {
  261.                 fprintf(zout, "%s\n", line);
  262.                 fclose(zout);
  263.                 return;
  264.         }
  265.         if (strcmp(temp, end) == 0) {   /* If end word */
  266.                 fclose(zout);   /* close the file */
  267.                 return;
  268.         }
  269.         match = strncmp(temp, lead, n);
  270.         if ((how == YESX) && (match == 0))
  271.                 temp += n;      /* Skip any lead */
  272.         fprintf(zout, "%s\n", temp);
  273.   }
  274. }
  275.  
  276. void getnames(buf, file, word)  /* Get the file & end word */
  277. /* [<][>][^][v][top][bottom][index][help] */
  278. char *buf, *file, *word;        /* from the buffer */
  279. {
  280.   char *temp;
  281.  
  282.   temp = buf;
  283.  
  284.   while (*temp != 0) {          /* Scan along buffer */
  285.         switch (*temp) {        /* Get file or end word */
  286.             case '>':
  287.                 strcpy(file, getstring(++temp));        /* Get the file name */
  288.                 break;
  289.             case '<':
  290.                 if (*(++temp) == '<') ++temp;   /* Skip 2nd < */
  291.                 strcpy(word, getstring(temp));  /* Get next word */
  292.                 break;
  293.             default:    temp++;
  294.         }
  295.   }
  296. }
  297.  
  298. void disembowel()
  299. /* [<][>][^][v][top][bottom][index][help] */
  300. {                               /* Unshar brutally! */
  301.   char buf[BUFSIZE];            /* Line buffer */
  302.   char file[BUFSIZE];           /* File name */
  303.   char word[BUFSIZE];           /* Word buffer */
  304.   char lead_string[BUFSIZE];    /* lead string */
  305.   char *p, *p1;
  306.   int ch;
  307.  
  308.   overrunchars = nulchars = 0;
  309.   while (1) {
  310.         ch = fgetline(stdin, NOWHITE, buf, sizeof buf);
  311.         if (ch == EOF) {
  312.                 if (nulchars + overrunchars != 0) fprintf(stderr,
  313.                                 "unshar: Discarded %lu characters from input.  Output may be garbled\n",
  314.                                 nulchars + overrunchars);
  315.                 return;
  316.         }
  317.         switch (firstword(buf)) {       /* Extract, depending on first word */
  318.             case CAT:
  319.                 getnames(buf, file, word);
  320.  
  321.                 /* Find the leading string. */
  322.                 p = buf;
  323.                 while (*p != '/') p++;
  324.                 p++;
  325.                 if (*p == '^') p++;     /* ^ has no width */
  326.                 p1 = p;
  327.                 while (*p1 != '/') p1++;
  328.                 strncpy(lead_string, p, (size_t) (p1 - p));
  329.  
  330.                 if (table == 0) {
  331.                         if ((numext == 0) || (mustget(file))) {
  332.                                 printf("unshar: Extracting  %s\n", file);
  333.                                 extract(NOX, file, word, lead_string);
  334.                         }
  335.                 } else {
  336.                         printf("  %s\n", file);
  337.                 }
  338.                 break;
  339.  
  340.             case GRES:
  341.             case SED:
  342.                 getnames(buf, file, word);
  343.  
  344.                 /* Find the leading string. */
  345.                 p = buf;
  346.                 while (*p != '/') p++;
  347.                 p++;
  348.                 if (*p == '^') p++;     /* ^ has no width */
  349.                 p1 = p;
  350.                 while (*p1 != '/') p1++;
  351.                 strncpy(lead_string, p, (size_t) (p1 - p));
  352.  
  353.                 if (table == 0) {
  354.                         if ((numext == 0) || (mustget(file))) {
  355.                                 printf("unshar: Extracting  %s\n", file);
  356.                                 extract(YESX, file, word, lead_string);
  357.                         }
  358.                 } else {
  359.                         printf("  %s\n", file);
  360.                 }
  361.                 break;
  362.             default:    break;
  363.         }
  364.   }
  365. }
  366.  
  367. void usage()
  368. /* [<][>][^][v][top][bottom][index][help] */
  369. {
  370.   fprintf(stderr, "Usage: unshar [-t] [-b] [-v] [-xfile] [file(s)]\n");
  371.   exit(0);
  372. }
  373. /* [<][>][^][v][top][bottom][index][help] */
  374.